function Map(sz) {
	this.size = sz || 3;
	this.data = {};
}
Map.OBJSIZE = 128;
Map.utilRenderObjFill = function(obj) {
	var i = (imgList[obj.texture||obj.tile_texture]);
	if (i && i.image) { return texture(i.image); }
	ambientMaterial(obj.fill || '#ccc');
}
Map.utilObjSize = function(obj) {
	var r = {x: Map.OBJSIZE, y: Map.OBJSIZE, z: Map.OBJSIZE};
	if (obj.class == 'wall') { r.y *= 3; }
	return r;
}
Map.renderObject = function(id, obj, flags, x, y, z) {
	mPush();
	flags = flags || {};
	var r = Map.utilObjSize(obj);
	mTranslate(x*Map.OBJSIZE, y*Map.OBJSIZE, z*Map.OBJSIZE);
	mTranslate(r.x/2, -(r.y/2), r.z/2);
	if (obj.class == 'tile') {
		mTranslate(0, Map.OBJSIZE/2, 0);
		Map.utilRenderObjFill(obj);
		mRotateX(radians(90));
		mPlane(id, Map.OBJSIZE);
	} else if (obj.class == 'wall') {
		mTranslate(0, 0, Map.OBJSIZE/2);
		Map.utilRenderObjFill(obj);
		mBox(id, r.x, r.y, 4);
	}
	mPop();
}
Map.prototype.render = function() {
	mPush();
	mTranslate(-this.size*Map.OBJSIZE/2, 0, -this.size*Map.OBJSIZE/2);
	this.IDtoXYZ = {};
	var id = 1;
	for (var p in this.data) {
		var vec = p.split(',');
		var n = 0;
		this.data[p].forEach(function(e) {
			var obj = objList[e.objType];
			if (!obj) return;
			this.IDtoXYZ[id] = [[vec[0], vec[1], vec[2]], n];
			Map.renderObject(id, obj, null, vec[0], vec[1], vec[2]);
			id++; n++;
		});
	}
	mPop();
}
